home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-14 | 38.8 KB | 1,362 lines | [TEXT/R*ch] |
- Unofficial MARATHON Specs
- release version v0.0 - January 19, 1995
-
- brought to you by:
-
- freidin@phoenix.princeton.edu (Bernie Freidin)
-
- special thanks to:
-
- pjcreath@phoenix.princeton.edu (Peter Creath)
- omv@cool-toys.mit.edu (Danimal)
- bhines@sdcc13.ucsd.edu (Clef)
- MORBID@resnova.com
-
- ...and of course:
-
- jon3@quads.uchicago.edu (Jason Jones)
-
- ------------------------------------------------------------------------------
- GENERAL INFORMATION
- ------------------------------------------------------------------------------
-
- Marathon consists of the following files:
-
- %"Marathon" (application program)
- %"Shapes" (contains graphics)
- %"Sounds" (contains sounds)
- %"Map" (contains level information)
- %"Music" (contains music information, but *not* the samples of the notes)
- %"Physics Model" (optional - contains physics information)
-
- %saved games (contains mostly level information)
- %films (contains sequence of keystrokes)
-
- The following information is contained in each file:
-
- "Marathon" (type 'APPL', creator '26.2')
-
- Program code, and the usual assortment of resources found in most Mac
- applications. The only interesting things here are the resources of type 'term',
- which contain the text displayed on the computer terminals in the game.
-
- "Shapes" (type 'shps')
-
- All graphic data for textures, sprites, and interfaces, stored as resources
- of type '.256'. There are also 'clut' resources (color tables), and 'PICT'
- resources that contain the pictures displayed between levels. I'm not sure
- whether the color tables here are used, or the color tables stored in the main
- application. See below for more information on the format of '.256' resources.
-
- "Sounds" (type 'sndz')
-
- All game sounds. These are stored as ordinary Mac 'snd ' resources, of format
- 1. See Inside Macintosh for more information.
-
- "Map" (type 'scen')
-
- Map information for all levels, stored in the data fork. See below for more
- information.
-
- "Music" (type 'msik')
-
- Music sequencing information, stored in the data fork. Exact format unknown,
- but is supposedly it is some form of MIDI .
-
- "Physics Model" (type 'phys')
-
- Physical infomation, stored in the data fork. There is also a 'text' resource
- put in by Jason giving a short description of some of the format for this file.
- See below for more information.
-
- saved games (type 'sgam')
-
- Same information as "Map" files, stored in the data fork. There should be
- only one level, however, and the 'EPNT' chunk is replaced by a 'PNTS' chunk (see
- below). Also contained in these files is a 'PICT' resource of a portion of the
- level map (as seen in the preview box), and a 'STR ' resource containing the
- level name.
-
- films (type 'film')
-
- Contains keystroke information necessary to replay a game. Exact format
- unknown.
-
- #define NONE -1
-
- typedef long fixed;
- typedef unsigned short angle;
- typedef struct shape_descriptor
- {
- char set;
- char frame;
- };
- typedef short world_distance;
- typedef struct world_point2d
- {
- world_distance x, y;
- };
-
- ------------------------------------------------------------------------------
- SHAPES INFORMATION
- ------------------------------------------------------------------------------
-
- Header format:
-
- Each '.256' resource starts with a 544 byte header:
-
- enum /* shapes classes */
- {
- _shapeUnused,
- _shapeTexture, /* RAW */
- _shapeSprite, /* RLE */
- _shapeInterface, /* RAW */
- _shapeScenery /* RLE */
- };
-
- %_shapeUnused: not used
- %_shapeTexture: usually 128x128 pixels, but not always
- %_shapeSprite: all monsters, guns, objects..
- %_shapeInterface: everything that doesn't go in the window
- %_shapeScenery: ???
-
- struct shapes_header /* 544 bytes */
- {
- short type;
- short class;
- unsigned short flags;
-
- short color_count;
- short palette_count;
- long first_palette_address;
-
- short high_level_shapes_count;
- long high_level_shapes_table;
-
- short low_level_shapes_count;
- long low_level_shapes_table;
-
- short image_count;
- long image_table;
-
- short scale_factor;
- long size;
-
- short unused[253];
- };
-
- %type: always equals 3
- %class: see above
- %flags:
- %color_count: number of color entries in each palette
- %palette_count: number of palettes (different palettes are used for different
- "variations" of monsters)
- %first_palette_address: offset to first palette
- %high_level_shapes_count: number of high-level shapes
- %high_level_shapes_table: offset to table of addresses of high-level shape
- records
- %low_level_shapes_count: number of low-level shapes
- %low_level_shapes_table: offset to table of addresses of low-level shape records
- %image_count: number of images
- %image_table: offset to table of addresses of images
- %size: size of entire resource
-
- Palettes:
-
- Each palette contain color_count entries, where each entry has the following
- structure:
-
- struct color_entry /* 8 bytes */
- {
- short entry_number; /* ranges from 0 to color_count - 1 */
- unsigned short red;
- unsigned short green;
- unsigned short blue;
- };
-
- The palettes are stored consecutively with no gaps between.
-
- High-level shapes:
-
- These describe an entire animated sequence, complete with sound effects and
- frame rate information. The exact format is as follows:
-
- enum /* high-level shape flags */
- {
- };
-
- enum /* high-level shape types */
- {
- };
-
- struct high_level_shape /* 88 bytes */
- {
- short type;
- unsigned short flags;
-
- char name_length;
- char name[33];
-
- short view_count;
- short frames_per_view;
- short ticks_per_frame;
-
- short key_frame;
-
- short transfer_mode;
- short transfer_mode_period; /* in ticks */
-
- short first_frame_sound;
- short key_frame_sound;
- short last_frame_sound;
-
- short scale_factor;
-
- short unused[15];
-
- //frame information
- };
-
- %type: see above
- %flags: see above
- %name_length: length of name string (i.e. this is a Pascal string)
- %name: ASCII string
- %view_count: number of angles at which this animation can be viewed. This should
- only be 1, 2, 5, or 8.
- %frames_per_view: number of frames of animation
- %ticks_per_frame: speed of animation
- %key_frame: frame at which "something happens"?
- %transfer_mode:
- %transfer_mode_period: absolutely no idea..
- %first_frame_sound: 'snd ' resource to play at start of animation
- %key_frame_sound: 'snd ' resource to play at key frame
- %last_frame_sound: 'snd ' resource to play at end of animation
- %scale_factor:
-
- After this comes the frame information, which is a series of 2-byte words, each
- corresponding to a low-level shape. There will be view_count * frames_per_view
- entries, followed by 2 bytes of zero signifying to end of the animation. Note
- that if view_count equals 5, then it's really 8 * frames_per_view entries.
-
- Low-level shapes:
-
- These describe just one non-animated sprite, or one frame of an animated
- sequence. The exact format is as follows:
-
- enum /* low-level shape flags */
- {
- _lowShapeXMirror = 0x8000,
- _lowShapeYMirror = 0x4000,
- _lowShapeKeyObscure = 0x2000
- }
-
- %_lowShapeXMirror: indicates that the sprite is to be drawn from right to left
- rather than left to right
- %_lowShapeYMirror: similar to _lowShapeXMirror, but affects drawing vertically
- rather than horizontally. It doesn't seem to be implemented
- %_lowShapeKeyObscure: ???
-
- struct low_level_shape /* 36 bytes */
- {
- unsigned short flags;
-
- fixed minimum_light_intensity;
- short image_index;
- short x_origin, y_origin;
- short x_key, y_key;
- short left, right, top, bottom;
- short world_x_origin, world_y_origin;
-
- short unused[4];
- };
-
- %flags: see above
- %minimum_light_intensity: minimum light value that can be assigned to this
- image. Used for "bright" sprites, such as explosions, that are never supposed to
- be dark.
- %image_index: indicates which image is used to draw this low-level shape
- %x_origin, y_origin: center of shape? Who knows..
- %x_key, y_key: no idea..
- %left, top, right, bottom: defines the bounding rectangle?
- %world_x_origin, world_y_origin: no idea..
-
- Images:
-
- These contain the actual graphic data for the images. First is a header, then
- follows the scan start address table, and then the pixel data. The exact format
- of the pixel data depends on the type of shape (RAW or RLE).
-
- struct image_header /* 26 bytes */
- {
- short width;
- short height;
- short unknown[11]; /* ??? */
- };
-
- %width: width of image
- %height: height of image
-
- Next comes the scan start addresses. These are run-time calculated, so there is
- no need to provide valid information here. However, the right amount of space
- must be reserved for this block. The size of the block will be width * 4, plus 4
- bytes at the end (unknown?).
-
- And finally comes the actual image data. In RAW format, this is just a block
- of bytes, where each byte corresponds to one pixel. The pixels are stored top to
- bottom, then right to left. The color of a pixel can be determined by using the
- pixel value as an index into the palette.
- RLE format is a little different. It starts with a 2-byte command word. If
- this word is greater than zero, it signifies the start of a vertical run of
- pixels. The pixel data follows immediately, and the number of pixels is equal to
- the command word. If the command word is negative, it signifies the start of a
- vertical "skip" in which no pixels are drawn (a hole). The length of the skip
- will be equal to negative the value of the command word. If the command word is
- zero, it signifies the start of the next vertical column, which will start one
- pixel to the right of the start of the first column. The command words are
- repeated until the entire sprite is drawn.
-
- ------------------------------------------------------------------------------
- PHYSICS MODEL INFORMATION
- ------------------------------------------------------------------------------
-
- The Physics Model contains information on gravity, weapon speed, monster
- behavior, and many other things. I'm not sure where the default physics
- information is stored (there doesn't appear to be any in the Marathon
- application, nor the Map files..).
- Like the Map file, the Physics Model is made up of a number of "chunks", each
- of which contains a number of "entries". The following chunk types are known:
-
-
- Chunk types:
-
- 'mons': Monster information
- 'effe': Effect information
- 'proj': Projectile information
- 'phys': Physics information
- 'weap': Weapon information
-
- Each chunk starts with a header, which has the following format:
-
- struct physics_chunk_header /* 12 bytes */
- {
- long chunk_type;
- short unused[2];
- short entry_count;
- short entry_size;
- };
-
- %chunk_type: 4 character ASCII string signifying chunk type
- %entry_count: number of entries in chunk
- %entry_size: size of each entry
-
- Why do the Physics Model chunks follow a different format from the Map chunks?
-
- ------------------------------------------------------------------------------
- 'mons' chunk:
- ------------------------------------------------------------------------------
-
- The Monster chunk defines every monster in the game, including non-hostiles.
- A couple of things to note - first, different 'colored' monsters are defined seperately.
- Second, the monster chunk references the effects chunk for animations when they get hit,
- the projectile chunk for the projectiles they shoot (in the attack structure), and the
- shapes directly for their moving shapes.
-
- enum /* monster flags */
- {
- _monsterOmniscent = 0x00000001,
- _monsterFly = 0x00000002,
- _monsterAlien = 0x00000004,
- _monsterMajor = 0x00000008,
- _monsterMinor = 0x00000010,
- _monsterNoDrop = 0x00000020,
- _monsterFloat = 0x00000040,
- _monsterNoAttack = 0x00000080,
- _monsterSnipe = 0x00000100,
- _monsterInvisible = 0x00000200,
- _monsterSubInvisible = 0x00000400,
- _monsterKamakazi = 0x00000800,
- _monsterBerserk = 0x00001000,
- _monsterEnlarged = 0x00002000,
- _monsterDelayedHardDeath = 0x00004000,
- _monsterFiresSymmetrically = 0x00008000,
- _monsterNuclearHardDeath = 0x00010000,
- _monsterNoFireBackwards = 0x00020000,
- _monsterFlammable = 0x00040000
- };
-
- %_monsterOmniscent:
- %_monsterFly: monster can fly
- %_monsterAlien: moves slower on lower levels
- %_monsterMajor: type -1 is minor?
- %_monsterMinor: type +1 is major?
- %_monsterNoDrop: low levels cannot skip monster
- %_monsterFloat:
- %_monsterNoAttack: civilian, constantly runs to safety
- %_monsterSnipe: use long range weapon to attack from ledges
- %_monsterInvisible: monster is invisible
- %_monsterSubInvisible: monster is partially invisible
- %_monsterKamakazi: explodes if close to player, causing damage
- %_monsterBerserk: goes berserk when below 25% vitality
- %_monsterEnlarged: 25% larger
- %_monsterDelayedHardDeath: always dies soft, then switches to hard?
- %_monsterFiresSymmetrically:
- %_monsterNuclearHardDeath: screen turns white and slowly recovers
- %_monsterNoFireBackwards: can't turn more than 135 degrees to fire
- %_monsterFlammable: susceptible to flame unit
-
- Monsters unable to open doors have door retry masks of NONE
- Monsters unable to switch levels have min,max ledge deltas of 0
- Monsters unstopped by bullets have hit frames of NONE
-
- enum /* attack types */
- {
- };
-
- struct attack_struct /* 16 bytes */
- {
- short type;
-
- short repetitions;
- angle error;
-
- world_distance range;
- short attack_shape;
-
- world_distance dx;
- world_distance dy;
- world_distance dz;
- };
-
- %type: see above
- %repetitions: number of repetitions of attack
- %error: error added to firing angle
- %range: range of attack
- %attack_shape: attack occurs when keyframe is displayed
- %dx,dy,dz: attack vector (dx=out,dy=right,dz=up)
-
- enum /* damage flags */
- {
- };
-
- enum /* damage types */
- {
- };
-
- struct damage_struct /* 12 bytes */
- {
- short type;
- unsigned short flags;
-
- short base;
- short random;
- fixed scale;
- };
-
- %type: see above
- %flags: see above
- %base: base damage
- %random: random factor
- %scale: ??
-
- struct monster_entry /* 138 bytes */
- {
- short collection;
-
- short vitality;
- unsigned long immunities;
- unsigned long weaknesses;
- unsigned long flags;
-
- long class;
- unsigned long friends;
- unsigned long enemies;
-
- short activation_sound;
- short conversation_sound;
- short flaming_sound;
- short random_sound;
- short random_sound_mask;
-
- short carrying_item_type;
-
- world_distance radius;
- world_distance height;
- world_distance preferred_hover_height;
- world_distance minimum_ledge_delta;
- world_distance maximum_ledge_delta;
- fixed external_velocity_scale;
- short impact_effect;
- short melee_impact_effect;
-
- short half_visual_arc;
- short half_vertical_visual_arc;
- world_distance visual_range;
- world_distance dark_visual_range;
- short intelligence;
- short speed;
- short gravity;
- short terminal_velocity;
- short door_retry_mask;
- short shrapnel_radius; /* no shapnel if NONE */
- struct damage_struct shrapnel_damage;
-
- shape_descriptor hit_shapes;
- shape_descriptor hard_dying_shape; /* minus dead frame */
- shape_descriptor soft_dying_shape; /* minus dead frame */
- shape_descriptor hard_dead_shapes; /* NONE = vanishing */
- shape_descriptor soft_dead_shapes; /* NONE = vanishing */
- shape_descriptor stationary_shape;
- shape_descriptor moving_shape;
-
- short attack_frequency;
- struct attack_struct melee_attack;
- struct attack_struct ranged_attack;
- };
-
- %collection:
- %vitality: How much damage the monter can sustain
- %immunities: mask of what the monster is immune to
- %weaknesses: mask of what the monster is susceptible to
- %flags:
- %class: bit of which class the monster belongs to
- %friends: mask of friend classes
- %enemies: mask of enemy classes
- %activation_sound: sound made when monster is generated
- %conversation_sound: sound made in conversation (?)
- %flaming_sound: sound made when the monster gets TOZT'ed
- %random_sound: randomly played sound (?)
- %random_sound_mask: mask of when to play sound (??)
- %carrying_item: something the monster will drop (ex: alien weapon)
- %radius: radius of monster
- %height: height of monster
- %preffered_hover_height: height at which the monsters 'likes' to fly
- %maximum_ledge_delta: the maximum a monster can 'climb' up
- %minimum_ledge_delta: the maximum a monster can 'climb' down
- %external_velocity_scale: No idea (?!?!?)
- %impact effect: effeect to play when monster hits person {kamikazee?}
- %melee_impact_effect: effect to play when monster whacks person
- %half_visual_arc: horizontal visual range {side-to-side vision}
- %half_vertical_visual_arc: vertical visual range {up-down vision}
- %visual_range: range at which the monster can 'see' something
- %dark_visual_range: range at which monster can see in the 'dark' (?)
- %intelligence: hmmm... (???)
- %speed: how fast the monster goes
- %gravity: acceleration on falling monster (?)
- %terminal_velocity: maximum fall rate (?)
- %door_retry_mask: something to do with doors - which they can open? (??)
- %shrapnel_radius: blast radius when self destructing
- %shrapnel_damage: damage structure for self destruction
- %hit_shapes: shapes of monster being hit by bullets
- %hard/soft_dying_shape: shape of monster dying
- %hard/soft_dead_shape: shape of dead monster on floor
- %stationary_shape: monster not moving {sitting down, etc}
- %moving_shape: normal monster in motion
- %attack_frequency: how many ticks between attacks - melee is twice as often as ranged
- %melee_attack: attack structure for melee attacks
- %ranged_attack: attack structure for ranged attacks
-
-
- ------------------------------------------------------------------------------
- 'effe' chunk:
- ------------------------------------------------------------------------------
- This is all guesswork I've got from playing with the effects a bit. I'm not certain what the
- hell the flags are, although they always seem to be either 0 or 4..?
-
- struct effect_entry /* 138 bytes */
- {
- short collection;
- short shape;
- short flags;
- }
-
- %collection: Which collection the effect is from
- %animation: which animation it is
- %flags: unknown (???)
-
-
- ------------------------------------------------------------------------------
- 'proj' chunk:
- ------------------------------------------------------------------------------
-
- Projectiles are the bullets that everyone fires. No rocket science here.
-
- enum /* projectile flags */
- {
- _projectileGuided = 0x0001,
- _projectileNoAnimation = 0x0002,
- _projectilePersistent = 0x0004,
- _projectileAlien = 0x0008,
- _projectileGravity = 0x0010,
- _projectileNoHErr = 0x0020,
- _projectileNoVErr = 0x0040,
- _projectileHitSwitch = 0x0080,
- _projectilePositiveVErr = 0x0100,
- _projectileMelee = 0x0200
- };
-
- %_projectileGuided: tracks targets apparently - useless for user weapons at the moment
- %_projectileNoAnimation: projectile stops when animation loops - ex flamethrower
- %_projectilePersistent: ???
- %_projectileAlien: does less damage and moves slower on lower levels
- %_projectileGravity: projectile is affected by gravity
- %_projectileNoHErr: no horizontal error - spread is entirely vertical
- %_projectileNoVErr: no vertical error - spead is entirely horizontal
- %_projectileHitSwitch: projectile can toggle switches
- %_projectilePositiveVErr: positive vertical error - only shoots high? (??)
- %_projectileMelee: can use a monster's custom melee detonation (??)
-
- struct projectile_entry /* 36 bytes */
- {
- short collection;
- short shape_index;
-
- short detonation_effect;
-
- short contrail_effect;
- short ticks_between_contrails;
- short maximum_contrails;
-
- world_distance radius;
- world_distance area_of_effect;
-
- short damage_type;
- short damage_flags;
- short damage_base, damage_random
- fixed damage_scale;
-
- word flags;
-
- world_distance speed;
- world_distance maximum_range;
-
- short flyby_sound;
- };
-
- %collection: if -1 (NONE), then this is invisible
- %maximum_contrails: how many contrails will be left. if -1 (NONE), then this is treated as infinite
- %radius: proximity radius - can be zero and will still hit
- %area_of_effect: detonation radius - one target if = 0
-
- ------------------------------------------------------------------------------
- 'weap' chunk:
- ------------------------------------------------------------------------------
-
- Lots of stuff to play with here. Unfortunately, it seems like a fair amount of stuff
- is hardcoded, like where ammo is displayed, ammo shapes on the screen, weapon names, etc.
-
- struct weapon_entry /* 120 bytes */
- {
- short type;
- short class;
- unsigned short flags;
-
- short ammunition_type;
- short rounds_per_magazine;
- short secondary_ammunition_type;
- short secondary_rounds_per_magazine;
-
- fixed firing_light_intensity;
- short firing_intensity_decay_ticks;
-
- fixed idle_height;
- fixed bob_amplitude;
- fixed kick_height;
- fixed reload_height;
- fixed idle_width;
- fixed horizontal_amplitude;
-
- short collection;
- short idle_shape;
- short firing_shape;
- short reloading_shape;
- short shell_casing_shape;
- short charging_shape;
- short charged_shape;
-
- short primary_ticks_per_round;
- short secondary_ticks_per_round;
- short reload_ticks;
- short ready_ticks;
- short primary_recovery_ticks;
- short secondary_recovery_ticks;
- short primary_charging_ticks;
- short secondary_charging_ticks;
-
- world_distance primary_recoil_magnitude;
- world_distance secondary_recoil_magnitude;
-
- short primary_firing_sound;
- short secondary_firing_sound;
- short primary_click_sound;
- short secondary_click_sound;
- short reload_sound;
- short charging_sound;
- short primary_shell_casing_sound;
- short secondary_shell_casing_sound;
- short primary_sound_activation_range;
- short secondary_sound_activation_range;
-
- short primary_round_projectile_type;
- short secondary_round_projectile_type;
-
- short short primary_theta_error;
- short secondary_theta_error;
-
- short primary_dx;
- short primary_dz;
- short secondary_dx;
- short secondary_dz;
-
- short primary_burst_count;
- short secondary_burst_count;
-
- short instant_reload_tick;
- };
- %type: unknown (???)
- %class: unknown (???)
- %ammunition_type: what type of ammo gets used up
- ∞rounds_per_magazine: how many roungs you get to fire before reloading
- ∞secondary_ammunition_type: ammo for the secondary weapon (if any)
- %short secondary_rounds_per_magazine: rounds/clip for the secondary weapon (if any)
- %fixed firing_light_intensity: how much the room lights up when firing (?)
- %short firing_intensity_decay_ticks: how long the light lasts
- %fixed idle_height: how high the weapon appears when being held
- %fixed bob_amplitude: how much the weapon bounces when moving
- %fixed kick_height: recoil height
- %fixed reload_height: how far it goes up when reloading (?)
- %fixed idle_width: width of weapon when idle (???)
- %fixed horizontal_amplitude: side to side sway (???)
- %short collection: collection of shapes for the weapon
- %short idle_shape: shape when idle
- %short firing_shape: shape when firing
- %short reloading_shape: shape when reloading
- %short shell_casing_shape: the casing shape, if any.
- $short charging_shape: Shape when a weapon is being charged
- %short charged_shape: Shape when a weapon is charged
-
- %short primary_ticks_per_round: How many ticks to fire a round (?)
- %short secondary_ticks_per_round: How many ticks to fire a round (?)
- %short reload_ticks: ticks to reload weapon
- %short ready_ticks: ticks to 'draw' weapon
- %short primary_recovery_ticks: time to recover from recoil for primary weapon
- %short secondary_recovery_ticks: time to recover from recoil for secondary weapon
- %short primary_charging_ticks: time to charge primary weapon
- %short secondary_charging_ticks: time to charge secondary weapon
- %world_distance primary_recoil_magnitude: how far the weapon recoils when firing primary
- %world_distance secondary_recoil_magnitude: how far the weapon recoils when firing secondary
- %short primary_firing_sound: sound when firing primary weapon
- %short secondary_firing_sound: sound when firing secondary weapon
- %short primary_click_sound: primary weapon is empty
- %short secondary_click_sound: secondary weapon is empty
- %short reload_sound: sound when reloading
- %short charging_sound: sound when charing
- %short primary_shell_casing_sound: sound of casing for primary hitting ground
- %short secondary_shell_casing_sound: sound of casing for secondary hitting ground
- %short primary_sound_activation_range: (???)
- %short secondary_sound_activation_range: (???)
- %short primary_round_projectile_type: type of projectile fired from primary
- %short secondary_round_projectile_type: type of projectile fire from secondary
- %short primary_theta_error: 'spread' of the weapon for firing primary
- %short secondary_theta_error: 'spread' of the weapon for firing secondary
- %short primary_dx: displacement for the primary weapon firing in the horizontal direction.
- %short primary_dz: displacement for the primary weapon firing in the vertical direction
- %short secondary_dx: displacement for the secondary weapon firing in the horizontal direction
- %short secondary_dz: displacement for the primary weapon firing in the vertical direction
- %short primary_burst_count: burst fire for primary weapon
- %short secondary_burst_count: burst fire for secondary weapon
- %short instant_reload_tick: no idea (?)
-
- ------------------------------------------------------------------------------
- MAP INFORMATION
- ------------------------------------------------------------------------------
-
- The Map file is by far the most complex of all the Marathon files. It
- contains all information about the structure and layout of the levels. Most
- Marathon Map files contain multiple levels, which are stored as follows:
-
- header (128 bytes)
- level 1
- level 2
- level 3...
- ....
- level n
- trailer (n * 8 bytes)
-
- Each level contains a number of chunks. Not all chunks must be present, and
- they may be in any order, but levels will not function properly without certain
- chunks.
-
- The exact format for the header is as follows:
-
- struct map_header /* 128 bytes */
- {
- short type;
- unsigned short flags;
- char name[64];
- long unknown;
- long map_size;
- short level_count;
- short unused[25]; //not quite..
- };
-
- %type: usually zero, as far as I can see.
- %flags: usually zero, as far as I can see.
- %name: ASCII string, zero terminated, up to 64 characters. Usually "Merged Map
- Files", but for saved games this is the name of the file.
- %map_size: total size of map file, excluding trailer but including header
- %level_count: number of levels
-
- The trailer contains one entry for each level:
-
- struct map_trailer_entry /* 8 bytes */
- {
- long offset;
- long size;
- };
-
- %offset: offset from start of file to this level
- %size: total size of all chunks in this level
-
- Each chunk starts with a header, followed by a number of entries (exact size
- and number of entries depends on the type of chunk). The format for the chunk
- header is as follows:
-
- struct map_chunk_header /* 12 bytes */
- {
- long chunk_type;
- long offset;
- long size;
- //..rest of chunk data follows
- };
-
- %chunk_type: 4 character ASCII string signifying chunk type
- %offset: offset from start of this level (not start of file) to next chunk
- %size: size of chunk
-
- Chunk types:
-
- 'iidx': exclusion zone chunk
- 'EPNT': vertex chunk (with extra info)
- 'PNTS': vertex chunk
- 'LINS': line chunk
- 'SIDS': side chunk
- 'POLY': polygon chunk
- 'NAME': name chunk (name of level)
- 'LITE': light source chunk
- 'NOTE': note chunk (text in automap)
- 'OBJS': object chunk
- 'p
- th': ???
- 'Minf': map-info chunk (?) (physics and environment info)
- 'plac': placement chunk
- 'door': ??? not used?
- 'plat': platform chunk (elevators, doors..)
- 'plyr': player chunk
- 'dwol': ???
- 'mobj': ???
- 'alin': ???
- 'apol': ???
- 'mOns': monster chunk??
- 'fx ': effects chunk??
- 'bang': ???
- 'PLAT': ???
-
- #define MAXIMUM_VERTICES 1024
- #define MAXIMUM_LINES 1024
- #define MAXIMUM_SIDES 1024
- #define MAXIMUM_POLYGONS 256
- #define MAXIMUM_LIGHTSOURCES 32
- #define MAXIMUM_OBJECTS 256
-
- ------------------------------------------------------------------------------
- 'EPNT' / 'PNTS' chunk:
- ------------------------------------------------------------------------------
-
- Each 'PNTS' entry is of type world_point2d.
- Each 'EPNT' entry has the following structure:
-
- enum /* vertex flags */
- {
- _vertexSolid = 0x0001,
- _vertexMultipleHeights = 0x0002
- };
-
- %_vertexSolid: ???
- %_vertexMultipleHeights: adjacent polygons have different heights
-
- struct vertex_entry /* 16 bytes */
- {
- unsigned short flags;
-
- world_distance highest_floor;
- world_distance lowest_ceiling;
-
- world_point2d vertex;
- world_point2d transformed;
-
- short polygon_index;
- };
-
- %flags: see above
- %highest_adjacent_floor: highest adjacent floor height
- %lowest_adjacent_ceiling: lowest adjacent ceiling height
- %vertex: coordinates of vertex
- %transformed: ???
- %polygon_index: ???
-
- ------------------------------------------------------------------------------
- 'LINS' chunk:
- ------------------------------------------------------------------------------
-
- enum /* line flags */
- {
- _lineSolid = 0x4000,
- _lineTransparent = 0x2000,
- _lineLandscaped = 0x1000,
- _lineElevated = 0x0800,
- _lineVariableElevation = 0x0400
- };
-
- %_lineSolid:
- %_lineTransparent:
- %_lineLandscaped:
- %_lineElevated:
- %_lineVariableElevation:
-
- struct line_entry /* 32 bytes */
- {
- short vertex_indexes[2];
- unsigned short flags;
-
- world_distance length;
- world_distance highest_floor;
- world_distance lowest_ceiling;
-
- short left_side_index;
- short right_side_index;
-
- short left_polygon_index;
- short right_polygon_index;
-
- short unused[6];
- };
-
- %vertex_indexes: endpoints of line
- %flags: see above
- %length: length of line
- %highest_floor: highest adjacent floor height
- %lowest_ceiling: lowest adjacent ceiling height
- %left_side_index:
- %right_side_index:
- %left_polygon_index:
- %right_polygon_index:
-
- ------------------------------------------------------------------------------
- 'SIDS' chunk:
- ------------------------------------------------------------------------------
-
- enum /* side flags */
- {
- _sideControlPanelStatus = 0x0001,
- _sideControlPanel = 0x0002,
- _sideRepairSwitch = 0x0004
- };
-
- %_sideControlPanelStatus:
- %_sideControlPanel:
- %_sideRepairSwitch:
-
- enum /* side types */
- {
- _sideFull,
- _sideHigh,
- _sideLow,
- _sideComposite,
- _sideSplit
- };
-
- %_sideFull: primary texture is mapped from ceiling down to floor
- %_sideHigh: primary texture is mapped from ceiling downwards
- %_sideLow: primary texture is mapped from floor upwards
- %_sideComposite: primary texture is mapped from ceiling down to floor, secondary
- texture is mapped ???
- %_sideSplit: primary texture is mapped from ceiling downards, and secondary
- texture is mapped from floor upwards
-
- enum /* control panel side types */
- {
- _panelOxygen,
- _panelShield,
- _panelDoubleShield,
- _panelTripleShield,
- _panelLightSwitch
- _panelPlatformSwitch,
- _panelPatternBuffer,
- _panelUnused,
- _panelCommTerminal
- _panelSwitch,
- _alienPanelDoubleShield
- _alienPanelTripleShield,
- _alienPanelPlatformSwitch,
- _alienPanelPatternBuffer
- };
-
- enum /* transfer modes (for sides and polygons) */
- {
- tNormal,
- tFadeToBlack,
- tInvisible,
- tSubInvisible,
- tPulsate, /* polygons only */
- tWobble, /* polygons only */
- tFastWobble, /* polygons only */
- tStatic,
- tSubStatic,
- tLandscape,
- tSmear, /* flat shading */
- tFadeOutStatic,
- tPulsateStatic,
- tFoldIn,
- tFoldOut,
- tHorizSlide,
- tFastHorizSlide,
- tVertSlide,
- tFastVertSlide,
- tWander,
- tFastWander
- };
-
- %tNormal: normal texture mapping
- %tFadeToBlack:
- %tInvisible:
- %tSubInvisible:
- %tPulsate:
- %tWobble:
- %tFastWobble:
- %tStatic:
- %tSubStatic:
- %tLandscape: direct copy (no texture mapping). This is typically used to draw
- the view outside of windows.
- %tSmear: fill polygon with pixel (0,0)
- %tFadeOutStatic:
- %tPulsateStatic:
- %tFoldIn:
- %tFoldOut:
- %tHorizSlide:
- %tFastHorizSlide:
- %tVertSlide:
- %tFastVertSlide:
- %tWander:
- %tFastWander:
-
- struct side_texture_struct /* 6 bytes */
- {
- world_distance x0, y0;
- shape_descriptor texture;
- };
-
- %x0,y0: texture offsets
- %texture: specifies texture set (first byte) and texture (second byte)
-
- struct side_exclusion_zone /* 16 bytes */
- {
- world_point2d e0, e1, e2, e3;
- };
-
- %e0,e1,e2,e3:
-
- struct side_entry /* 64 bytes */
- {
- short type;
- unsigned short flags;
-
- struct side_texture_struct primary_texture;
- struct side_texture_struct secondary_texture;
- struct side_texture_struct transparent_texture;
-
- struct side_exclusion_zone exclusion_zone;
-
- short control_panel_type;
- short control_panel_permutation;
-
- short primary_transfer_mode;
- short secondary_transfer_mode;
- short transparent_transfer_mode;
-
- angle direction;
- short line_index;
-
- short unused[6];
- };
-
- ------------------------------------------------------------------------------
- 'POLY' chunk:
- ------------------------------------------------------------------------------
-
- enum /* polygon flags */
- {
- _polygonDetached = 0x4000,
- _polygonPlatformInitiallyOff = 0x2000,
- _polygonPlatformInitiallyExtended = 0x1000
- };
-
- %_polygonDetached: ???
- %_polygonPlatformInitiallyOff: platform is initially off
- %_polygonPlatformInitiallyExtended: platform is initially extended
-
- enum /* polygon types */
- {
- _polygonNormal,
- _polygonItemImpassable,
- _polygonMonsterImpassable,
- _polygonMinorDamage,
- _polygonMajorDamage,
- _polygonPlatform,
- _polygonLightOnTrigger,
- _polygonPlatformOnTrigger,
- _polygonLightOffTrigger,
- _polygonPlatformOffTrigger,
- _polygonTeleporter,
- _polygonGlueTrigger,
- _polygonSuperglue,
- _polygonMustExplore,
- _polygonExit
- };
-
- struct polygon_entry /* 128 bytes */
- {
- short type;
- unsigned short flags;
- short permutation;
-
- short vertex_count;
- short vertex_index[8];
- short line_index[8];
-
- shape_descriptor floor_texture;
- shape_descriptor ceiling_texture;
- world_distance floor_height;
- world_distance ceiling_height;
- short floor_lightsource_index;
- short ceiling_lightsource_index;
-
- long area;
-
- short first_object;
-
- short first_exclusion_zone_index;
- short line_exclusion_zone_count;
- short point_exclusion_zone_count;
-
- short floor_transfer_mode;
- short ceiling_transfer_mode;
-
- short adjacent_polygon_index[8];
-
- short first_neighbor_index;
- short neighbor_count;
-
- world_point2d center;
-
- short side_index[8];
-
- short unused[10];
- };
-
- ------------------------------------------------------------------------------
- 'NAME' chunk:
- ------------------------------------------------------------------------------
-
- ------------------------------------------------------------------------------
- 'LITE' chunk:
- ------------------------------------------------------------------------------
-
- enum /* light flags */
- {
- _lightAutotriggered = 0x4000;
- };
-
- enum /* light types */
- {
- _lightNormal,
- _lightRheostat,
- _lightFlourescent,
- _lightStrobe,
- _lightFlicker,
- _lightPulsate,
- _lightAnnoying,
- _lightEnergyEfficient
- };
-
- enum /* light modes */
- {
- _lightTurningOn,
- _lightOn,
- _lightTurningOff,
- _lightOff,
- _lightToggle
- };
-
- struct lightsource_entry /* 32 bytes */
- {
- unsigned short flags;
-
- short type;
- short mode;
- short phase;
-
- fixed minimum_intensity;
- fixed maximum_intensity;
- short period;
-
- fixed intensity;
-
- short unused[5];
- };
-
- ------------------------------------------------------------------------------
- 'NOTE' chunk:
- ------------------------------------------------------------------------------
-
- ------------------------------------------------------------------------------
- 'OBJS' chunk:
- ------------------------------------------------------------------------------
-
- enum /* map object types */
- {
- _savedMonster,
- _savedObject,
- _savedItem,
- _savedPlayer,
- _savedGoal
- };
-
- struct map_object_entry /* 16 bytes */
- {
- short type;
- short index;
- short facing;
- short polygon_index;
- world_point2d location;
- short unused[2];
- };
-
- ------------------------------------------------------------------------------
- 'p
- th' chunk:
- ------------------------------------------------------------------------------
-
- ------------------------------------------------------------------------------
- 'Minf' chunk:
- ------------------------------------------------------------------------------
-
- enum /* mission flags */
- {
- _missionNone = 0x0000,
- _missionExtermination = 0x0001,
- _missionExploration = 0x0002,
- _missionRetrieval = 0x0004,
- _missionRepair = 0x0008,
- _missionRescue = 0x0010
- };
-
- enum /* environment flags */
- {
- _environmentNormal = 0x0000,
- _environmentVacuum = 0x0001,
- _environmentMagnetic = 0x0002,
- _environmentRebellion = 0x0004,
- _environmentLowGravity = 0x0008
- };
-
- struct static_entry /* 86 bytes */
- {
- short environment_code;
-
- short physics_model;
-
- short song_index;
- unsigned short mission_flags;
- unsigned short environment_flags;
-
- short unused[4];
-
- char level_name[64];
- long entry_point_flags;
- };
-
- ------------------------------------------------------------------------------
- 'plat' chunk:
- ------------------------------------------------------------------------------
-
- enum /* platform types */
- {
- _platformInitiallyActive = 0x00000001,
- _platformInitiallyExtended = 0x00000002,
- _platformStopsAtEachLevel = 0x00000004,
- _platformStopsAtInitialLevel = 0x00000008,
- _platformActivatesAdjacentUponDeactivating = 0x00000010,
- _platformExtendsFloorToCeiling = 0x00000020,
- _platformExtendsFloor = 0x00000040,
- _platformExtendsCeiling = 0x00000080,
- _platformCausesDamage = 0x00000100,
- _platformNoActivateParent = 0x00000200,
- _platformOneShot = 0x00000400,
- _platformActivatesLight = 0x00000800,
- _platformDeactivatesLight = 0x00001000,
- _platformPlayerControllable = 0x00002000,
- _platformMonsterControllable = 0x00004000,
- _platformSafety = 0x00008000,
- _platformNoExternalActivate = 0x00010000,
- _platformUsesNativeHeights = 0x00020000,
- _platformDelaysBeforeActivate = 0x00040000,
- _platformActivatesAdjacentUponActivating = 0x00080000,
- _platformDeactivatesAdjacentUponActivating = 0x00100000,
- _platformDeactivatesAdjacentUponDeactivating = 0x00200000,
- _platformContractsSlow = 0x00400000,
- _platformActivatesAdjacentOnEachLevel = 0x00800000,
- _platformFloods = 0x01000000
- };
-
- struct platform_entry /* 16 bytes */
- {
- short type;
-
- short speed;
- short delay;
-
- short maximum_height;
- short minimum_height;
-
- unsigned long flags;
-
- short owner_polygon_index;
-
- short unused[8];
- };
-
-
- -----------------------------------------------------------------------------
- ------------------------------------------------------------------------------
-
- enum /* game options */
- {
- _gameMultiplayer = 0x0001,
- _gameReplenishAmmo = 0x0002,
- _gameReplenishWeapons = 0x0004,
- _gameReplenishSpecials = 0x0008,
- _gameReplenishMonsters = 0x0010,
- _gameNoMotionSensor = 0x0020,
- _gameOmniscientMap = 0x0040,
- _gameLoseItemsOnDeath = 0x0080,
- _gameDebugMap = 0x0100,
- _gameKillLimit = 0x0200,
- _gameNoTeams = 0x0400,
- _gamePenalizeDying = 0x0800,
- _gamePenalizeSuicide = 0x1000,
- _gameMapShowsItems = 0x2000,
- _gameMapShowsMonsters = 0x4000,
- _gameMapShowsProjectiles = 0x8000
- };
-
-